using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using ZoneFiveSoftware.Common.Data.Fitness;
using FilteredStatistics.Common;

namespace FilteredStatistics.Data
{
    class Template : IPluginSerializable
    {
        public Template(String name, FilterList filters)
        {
            Name = name;
            Filters = filters;
        }

        public Template(Stream stream, DataVersion version)
        {
            Deserialize(stream, version);
        }
      
#region IPluginSerializable members

        public override void Serialize(Stream stream)
        {
            SerializableString name = new SerializableString(Name);
            SerializableBool hideInDailyActivity = new SerializableBool(m_HideInDailyActivity);

            name.Serialize(stream);
            Filters.Serialize(stream);
            hideInDailyActivity.Serialize(stream);
        }

#endregion

#region Deserialization methods

        public void Deserialize_V1(Stream stream, DataVersion version)
        {
            SerializableString name = new SerializableString();

            name.Deserialize(stream, version);
            Filters.Deserialize(stream, version);

            Name = name;
        }

        public void Deserialize_V3(Stream stream, DataVersion version)
        {
            Deserialize_V1(stream, version);

            SerializableBool hideInDailyActivity = new SerializableBool(true);

            hideInDailyActivity.Deserialize(stream, version);

            m_HideInDailyActivity = hideInDailyActivity;
        }

#endregion

        protected void TriggerPropertyChangedEvent(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private void OnFilterListChanged(FilterList filterList, PropertyChangedEventArgs changedProperty)
        {
            if (changedProperty.PropertyName != "NewPlaceholderFilter")
            {
                TriggerPropertyChangedEvent("Filters");
            }
        }

        private void OnFilterChanged(Filter filter, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != "ValidTimes")
            {
                TriggerPropertyChangedEvent("Filter");
            }
            else
            {
                TriggerPropertyChangedEvent("ValidTimes");
            }
        }

        private void OnChildTemplatePropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != "ValidTimes")
            {
                TriggerPropertyChangedEvent("ChildTemplate");
            }
            else
            {
                TriggerPropertyChangedEvent("ValidTimes");
            }
        }

        public String Name
        {
            get { return m_Name; }
            set
            {
                if (Name != value)
                {
                    m_Name = value;

                    TriggerPropertyChangedEvent("Name");
                }
            }
        }

        public FilterList Filters
        {
            get { return m_Filters; }
            set
            {
                if (Filters != value)
                {
                    if (Filters != null)
                    {
                        // Unregister callbacks on current filters
                        Filters.FilterListChanged -= new FilterList.FilterListChangedEventHandler(OnFilterListChanged);
                        Filters.FilterChanged -= new FilterList.FilterChangedEventHandler(OnFilterChanged);

                        foreach (Filter currentFilter in Filters)
                        {
                            if (currentFilter.IsValid)
                            {
                                if (currentFilter.CriteriaFacade is TemplateFilterCriteria)
                                {
                                    foreach (TemplateNamedZone namedZone in currentFilter.Zones)
                                    {
                                        namedZone.Template.PropertyChanged -= new PropertyChangedEventHandler(OnChildTemplatePropertyChanged);
                                    }
                                }
                            }
                        }
                    }

                    // Build new filter list
                    FilterList newValue = new FilterList(null);
                    bool addedSelfAlready = false;

                    foreach (Filter currentFilter in value)
                    {
                        if (currentFilter.IsValid)
                        {
                            if (currentFilter.CriteriaFacade is TemplateFilterCriteria)
                            {
                                List<INamedZone> newSelection = new List<INamedZone>();

                                foreach (TemplateNamedZone namedZone in currentFilter.Zones)
                                {
                                    // Don't add self in filters, copy content
                                    if (namedZone.Template == this)
                                    {
                                        if (!addedSelfAlready)
                                        {
                                            foreach (Filter existingFilter in Filters)
                                            {
                                                newValue.AddFilter(existingFilter.Clone());
                                            }

                                            addedSelfAlready = true;
                                        }
                                    }
                                    else
                                    {
                                        newSelection.Add(namedZone);
                                    }
                                }

                                // Create a copy of teh filter
                                if (newSelection.Count > 0)
                                {
                                    Filter newFilter = new Filter();

                                    newFilter.Criteria = currentFilter.CriteriaFacade;
                                    newFilter.SetSelectedZones(newSelection);

                                    newValue.AddFilter(newFilter);
                                }
                            }
                            else
                            {
                                newValue.AddFilter(currentFilter.Clone());
                            }
                        }
                    }

                    if (Filters != null)
                    {
                        newValue.Activity = Filters.Activity;
                    }
                    m_Filters = newValue;

                    if (Filters != null)
                    {
                        Filters.FilterListChanged += new FilterList.FilterListChangedEventHandler(OnFilterListChanged);
                        Filters.FilterChanged += new FilterList.FilterChangedEventHandler(OnFilterChanged);
                    }

                    TriggerPropertyChangedEvent("FilterList");
                }
            }
        }

        public bool ShowOnlyInSettings
        {
            get { return m_HideInDailyActivity; }
            set
            {
                if (m_HideInDailyActivity != value)
                {
                    m_HideInDailyActivity = value;

                    TriggerPropertyChangedEvent("ShowOnlyInSettings");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private String m_Name;
        private FilterList m_Filters = null;
        private bool m_HideInDailyActivity = false;
    }
}
